package pl.prv.polanie.client.widgets.schedule.widgets;

import pl.prv.polanie.client.Planner;
import pl.prv.polanie.client.dto.CSPreferenceDTO;
import pl.prv.polanie.client.model.CacheService;
import pl.prv.polanie.client.model.ContextSettings;
import pl.prv.polanie.client.model.DataProvider;
import pl.prv.polanie.client.widgets.schedule.Day;
import pl.prv.polanie.client.widgets.schedule.LecturerPreferences;
import pl.prv.polanie.client.widgets.schedule.Schedule;
import pl.prv.polanie.client.widgets.schedule.ScheduleUtil;
import pl.prv.polanie.client.widgets.schedule.ScheduleView;

import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.AbsolutePanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.MouseListenerAdapter;
import com.google.gwt.user.client.ui.Widget;

public class DraggableZone extends AbsolutePanel implements DraggingListener {
	
	private static final String STYLE_DRAGGABLE_ZONE = "my-DraggableZone";
	private static final String STYLE_ONDRAGGINGELEMENT = "my-DraggableZone-onDraggingElement";
	private static final String STYLE_DRAGGABLE_ZONE_HANDLER = "my-DraggableZoneHandler";

	
	private int borderWidth = 1;
	
	/** Wskazuje, czy obiekt jest uzyty jako koszyk na subjectEvents (true),
	 * czy moze w konkretnym dniu na podziale. */
	boolean isSubjectEventsCart = false;
	
//	/** Referencja do tworzonej w danej chwili preferencji wykladowcy */
//	LecturerPreferences lecturerPreferencesWhileCreating = null;

	private Schedule parentSchedule = null;
	
	/**
	 * odleglosc od gory, w ktorej zaczeto tworzyc lecturerPreferences.
	 */
	int initialTopWhileCreating = 0;
	
	
	/**
	 * Wskazuje, czy w danym momencie jest draggowana kontrolka lecturerPreferences.
	 */
	boolean lecturerPreferencesDraggingInProgress = false;
	
	Label handler = new Label();
	
	public DraggableZone() {
		this(false);
	}
	
	
	public DraggableZone(boolean isSubjectEevntsCart) {
		this.isSubjectEventsCart = isSubjectEevntsCart;
		
		setStyleName(STYLE_DRAGGABLE_ZONE);
		
		handler.setStyleName(STYLE_DRAGGABLE_ZONE_HANDLER);
		handler.addMouseListener(new MouseListenerAdapter() {
//			@Override
			public void onMouseDown(Widget sender, int x, int y) {
				// TODO Auto-generated method stub
				super.onMouseDown(sender, x, y);
				runOnMouseDown(x, y);
			}
		});
		
		add(handler, 0, 0);
//		sinkEvents(Event.ONCLICK|Event.ONMOUSEDOWN|Event.ONMOUSEMOVE|Event.ONMOUSEUP|Event.ONDBLCLICK);
	}
	
	public void addStyleOnDragging() {
		addStyleName(STYLE_ONDRAGGINGELEMENT);
	}
	
	public void removeStyleOnDragging() {
		removeStyleName(STYLE_ONDRAGGINGELEMENT);
	}
	
	
	/**
	 * x, y - wspolrzedne eventa w oknie przegladarki
	 * 
	 * y - docelowe polozenie eventa w oknie przegladarki
	 */
	public void onDragging(Widget sender, int x, int y, int draggedWidgetYOffset) {

		//porownanie wspolrzednych eventa z polozeniem DraggableZone
		if( (x > this.getAbsoluteLeft() - Window.getScrollLeft())
				&& (x < this.getAbsoluteLeft() - Window.getScrollLeft() + this.getOffsetWidth() ) 
				&& (y >= this.getAbsoluteTop() - Window.getScrollTop())
				&& (y < this.getAbsoluteTop() - Window.getScrollTop() + this.getOffsetHeight())
		) {
			
			if (y < getAbsoluteTop() - Window.getScrollTop()) {
				y = getAbsoluteTop() - Window.getScrollTop();
			}

			addStyleOnDragging();
			
			int finalY =
				y
				- DOM.getAbsoluteTop(this.getElement())
				+ DOM.getElementPropertyInt(this.getElement(), "scrollTop")
				+ Window.getScrollTop();
			
			if (CacheService.isFullTimeSemesterSelected()) {
				finalY = (finalY / 9) * 9;
			} else {
				finalY = (int)((finalY / 4.5) * 4.5);
			}
			
			
			
			if (isSubjectEventsCart) {
//				Planner.log("DZ: dragguje nad eventsCartem");
			}
			
			if (isSubjectEventsCart) {
//				Planner.log("DZ: dragguje nad eventsCartem 1");
				this.add(sender);
			} else {
				if (sender instanceof LecturerPreferences) {
//					Planner.log("DZ: dragguje nad eventsCartem 2");
//					Planner.log("DraggableZone.onDragging() przeciagam LecturerPreferences"); 
					LecturerPreferences lp = (LecturerPreferences) sender;
					int top = finalY;
					int height = lp.getOffsetHeight();
					
//					Planner.log("DODAJE KONTROLKE finalY " + finalY);
					if (isResizingPossible(top, height)) {
						this.add(sender, 0, finalY);
//						Planner.log("DraggableZone.onDragging() nowa pozycja dozwolona");
					}
				} else {
//					Planner.log("DZ: dragguje nad eventsCartem ");
//					Planner.log("DODAJE KONTROLKE XXXXXXXXXXXXXXXXXXXXXXXX  finalY " + finalY);
					this.add(sender, 0, finalY);
				}
				
			}
			//add(sender);
			//sender.setHeight(this.getOffsetHeight() + "px");
		} else {
			removeStyleOnDragging();
		}
	}
	
	
	/**
	 * 
	 * @param x
	 * @param y
	 */
	protected void runOnMouseDown(int x, int y) {
		
//		Planner.log("DraggableZone.runOnMouseDown: " + "KLIK NA DZ " + parentSchedule.getScheduleView());
		
		//TODO dorzucic warunek na rodzaj podzialu zajec
		if (ContextSettings.isAdminUserSignedIn()) {
			
			//parentSchedule.getScheduleView() == ScheduleView.LECTURER ||
			if (
					parentSchedule.getScheduleView() == ScheduleView.LECTURER_PREFERENCES
			) {
				
				if (parentSchedule.getActiveLecturerPreferences() == null) {
					
					
					//USUNIECIE ZAZNACZENIA NA SE
					parentSchedule.cleanSubjectEventSelection();
					parentSchedule.cleanSubjectEventSelectionInTable();
					parentSchedule.hideSubjectEventEditionWidget();
					parentSchedule.hideSubjectEventsHints();
					
					if (!parentSchedule.isScheduleViewLecturerPreferences()) {
						parentSchedule.hideLecturerPreferences();
					}
					parentSchedule.hideHeaderLabelHints();
					
					
					
					Day day = getParentDay();
					
					int finalY = ((y) / 9) * 9;
					int startTime = ScheduleUtil.convertFromPixelsToStartTime(finalY, CacheService.isFullTimeSemesterSelected());
					
					initialTopWhileCreating = finalY;
					
					long pt = DataProvider.getDefaultPreferenceTypeID();
					
					long calendarDayID = -1;
					if (day != null) {
						calendarDayID = day.getCalendarDayDTO().getId();
					}
					
					
					CSPreferenceDTO csp = new CSPreferenceDTO();
					csp.setCalendarDayID(calendarDayID);
					csp.setPreferenceTypeID(pt);
					csp.setDuration(new Integer(0));
					csp.setStartTime(new Integer(startTime));
					csp.setLecturerID(getParentSchedule().getFilterPropertyLecturerID());
					
					
					
					
					if (day != null) {
						LecturerPreferences createdLP = parentSchedule.addCSPreferences(csp);
						parentSchedule.setActiveLecturerPreferences(createdLP);
						boolean whileCreating = true;
						createdLP.setResizingModeOn(whileCreating);
					}
					
				}
			}
			
		}
		
	}

	
	//tu byl problem
//	protected void runOnMouseMove(int x, int y) {
//		try {
//			if (parentSchedule.getActiveLecturerPreferences() != null) {
//				parentSchedule.setActiveLecturerPreferences(null);
//			}
//		} catch (Exception e) {
////			Planner.log("DraggableZone.runOnMouseMove() parentSchedule == null"); 
//		}
//	}
	
	/**
	 * Funkcja wywolywaba
	 * @param x
	 * @param y
	 */
	protected void runOnMouseMoveWithButtonDown(int x, int y) {
		if (parentSchedule != null) {
			
			LecturerPreferences activeLP = parentSchedule.getActiveLecturerPreferences();
			if (activeLP != null && getWidgetIndex(activeLP) != -1) {
				
				int widgetTop = this.getWidgetTop(activeLP);
				//int widgetBottom = widgetTop + activeLP.getOffsetHeight();

				if (y > widgetTop) {
					//zmiana rozmiaru w dol
					
					int proposedTop = widgetTop;
					int proposedHeight = ((y - widgetTop) / 9) * 9;
//					int finalY = ((y) / 9) * 9;
					
//					if (proposedTop < 0) {
//						proposedTop = 0;
//					}
					
					if (isResizingPossible(proposedTop, proposedHeight)) {
						activeLP.setHeight(proposedHeight + "px");
					}
				}
				
			}
			
		}
	}
	
	/**
	 * Sprawdza czy aktywny (w obrebie calego planu) lecturerPreferences o podanej
	 * pozycji i wysokosci nie bedzie kolidowal z innymi kontrolkami lecturerPreferences w obrebie draggableZone.
	 * @param top
	 * @param height
	 * @return
	 */
	public boolean isResizingPossible(int top, int height) {
		LecturerPreferences activeLP = parentSchedule.getActiveLecturerPreferences();
		if (activeLP == null) {
//			GWT.log("DraggableZone.isResizingPossible() activeLP == null", null); 
			return false;
		}
		
		for (int i = 0; i < this.getWidgetCount(); i++) {
			Widget w = this.getWidget(i);
			if (w instanceof LecturerPreferences) {
				LecturerPreferences lp = (LecturerPreferences)w;
				
				
				if (lp != activeLP) {
//					GWT.log("DraggableZone.isResizingPossible() sprawdzam z innym lecturerPreferences i = " + i, null);
					int lpTop = getWidgetTop(lp);
					int lpHeight = lp.getOffsetHeight();
					
//					GWT.log("DraggableZone.isResizingPossible() proponowane: " + top + ", " + height, null);
//					GWT.log("DraggableZone.isResizingPossible() istniejacy: " + lpTop + ", " + lpHeight, null);
					
					//1.
					if (top <= lpTop && (top + height > lpTop)) {
//						GWT.log("DraggableZone.isResizingPossible() przypadek 1.", null);
						return false;
					}
					
					//3.
					if (top > lpTop && top < lpTop + lpHeight) {
//						GWT.log("DraggableZone.isResizingPossible() przypadek 2.", null);
						return false;
					}
				}
			}
		}
		
		
		if (top + height > getOffsetHeight()) {
//			GWT.log("DraggableZone.isResizingPossible() przypadek 3.", null);
			return false;
		}
		return true;
	}
	
	
	
	protected void runOnMouseUp() {
		if (parentSchedule != null) {
			LecturerPreferences activeLP = parentSchedule.getActiveLecturerPreferences();
			if (activeLP != null) {
//				Planner.log("DZ wysokosc " + activeLP.getOffsetHeight());
				if (activeLP.getOffsetHeight() == 0) {
					remove(activeLP);
				}
				parentSchedule.setActiveLecturerPreferences(null);
			}
		}
	}
	
	
	protected void runOnClick() {
		Planner.log("DraggableZone.runOnClick: " + "");
		if (parentSchedule.getActiveLecturerPreferences() != null) {
			parentSchedule.setActiveLecturerPreferences(null);
		}
		parentSchedule.cleanSubjectEventSelection();
	}
	
	private int getEventX(Event event) {
		int x = DOM.eventGetClientX(event)
		- DOM.getAbsoluteLeft(this.getElement())
		+ DOM.getElementPropertyInt(this.getElement(), "scrollLeft")
		+ Window.getScrollLeft();
		return x;
	}
	
	
	private int getEventY(Event event) {
		int y = DOM.eventGetClientY(event)
		- DOM.getAbsoluteTop(this.getElement())
		+ DOM.getElementPropertyInt(this.getElement(), "scrollTop")
		+ Window.getScrollTop();
		return y;
	}

	public boolean isSubjectEevntsCart() {
		return isSubjectEventsCart;
	}
	
	
	
	public Day getParentDay() {
		Widget w = getParent();
		
		while (w != null) {
			if (w instanceof Day) {
				return (Day)w;
			}
			w = w.getParent();
		}
		
		return null;
	}

	

	public Schedule getParentSchedule() {
		return parentSchedule;
	}


	public void setParentSchedule(Schedule parentSchedule) {
		this.parentSchedule = parentSchedule;
	}
	
	
	
}
 